home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
ibmcom_c.zip
/
IBMCOM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-18
|
22KB
|
500 lines
/*****************************************************************************
* ibmcom.c *
*****************************************************************************
* DESCRIPTION: This file contains a set of routines for doing low-level *
* serial communications on the IBM PC. It was translated *
* directly from Wayne Conrad's IBMCOM.PAS version 3.1, with *
* the goal of near-perfect functional correspondence between *
* the Pascal and C versions. *
* *
* REVISIONS: 18 OCT 89 - RAC - Original translation from IBMCOM.PAS, with *
* liberal plagiarism of comments from the *
* Pascal. *
*****************************************************************************/
#include <stdio.h>
#include <dos.h>
#include "ibmcom.h"
/*****************************************************************************
* 8250 Definitions *
*****************************************************************************/
/* Offsets to various 8250 registers. Taken from IBM Technical */
/* Reference Manual, p. 1-225 */
#define TXBUFF 0 /* Transmit buffer register */
#define RXBUFF 0 /* Receive buffer register */
#define DLLSB 0 /* Divisor latch LS byte */
#define DLMSB 1 /* Divisor latch MS byte */
#define IER 1 /* Interrupt enable register */
#define IIR 2 /* Interrupt ID register */
#define LCR 3 /* Line control register */
#define MCR 4 /* Modem control register */
#define LSR 5 /* Line status register */
#define MSR 6 /* Modem status register */
/* Modem control register bits */
#define DTR 0x01 /* Data terminal ready */
#define RTS 0x02 /* Request to send */
#define OUT1 0x04 /* Output #1 */
#define OUT2 0x08 /* Output #2 */
#define LPBK 0x10 /* Loopback mode bit */
/* Modem status register bits */
#define DCTS 0x01 /* Delta clear to send */
#define DDSR 0x02 /* Delta data set ready */
#define TERI 0x04 /* Trailing edge ring indicator */
#define DRLSD 0x08 /* Delta Rx line signal detect */
#define CTS 0x10 /* Clear to send */
#define DSR 0x20 /* Data set ready */
#define RI 0x40 /* Ring indicator */
#define RLSD 0x80 /* Receive line signal detect */
/* Line control register bits */
#define DATA5 0x00 /* 5 Data bits */
#define DATA6 0x01 /* 6 Data bits */
#define DATA7 0x02 /* 7 Data bits */
#define DATA8 0x03 /* 8 Data bits */
#define STOP1 0x00 /* 1 Stop bit */
#define STOP2 0x04 /* 2 Stop bits */
#define NOPAR 0x00 /* No parity */
#define ODDPAR 0x08 /* Odd parity */
#define EVNPAR 0x18 /* Even parity */
#define STKPAR 0x28 /* Stick parity */
#define ZROPAR 0x38 /* Zero parity */
/* Line status register bits */
#define RDR 0x01 /* Receive data ready */
#define ERRS 0x1E /* All the error bits */
#define TXR 0x20 /* Transmitter ready */
/* Interrupt enable register bits */
#define DR 0x01 /* Data ready */
#define THRE 0x02 /* Tx buffer empty */
#define RLS 0x04 /* Receive line status */
/*****************************************************************************
* Names for Numbers *
*****************************************************************************/
#define MAX_PORT 4
#define TRUE 1
#define FALSE 0
/*****************************************************************************
* Global Data *
*****************************************************************************/
/* UART i/o addresses. Values depend upon which COMM port is selected */
int uart_data; /* Data register */
int uart_ier; /* Interrupt enable register */
int uart_iir; /* Interrupt identification register */
int uart_lcr; /* Line control register */
int uart_mcr; /* Modem control register */
int uart_lsr; /* Line status register */
int uart_msr; /* Modem status register */
char com_installed; /* Flag: Communications routines installed */
int intnum; /* Interrupt vector number for chosen port */
char i8259bit; /* 8259 bit mask */
char old_i8259_mask; /* Copy as it was when we were called */
char old_ier; /* Modem register contents saved for */
char old_mcr; /* restoring when we're done */
void interrupt (*old_vector)(); /* Place to save COM1 vector */
/* Transmit queue. Characters to be transmitted are held here until the */
/* UART is ready to transmit them. */
#define TX_QUEUE_SIZE 16 /* Transmit queue size. Change to suit */
char tx_queue[TX_QUEUE_SIZE];
int tx_in; /* Index of where to store next character */
int tx_out; /* Index of where to retrieve next character */
int tx_chars; /* Count of characters in queue */
/* Receive queue. Received characters are held here until retrieved by */
/* com_rx() */
#define RX_QUEUE_SIZE 4096 /* Receive queue size. Change to suit */
char rx_queue[RX_QUEUE_SIZE];
int rx_in; /* Index of where to store next character */
int rx_out; /* Index of where to retrieve next character */
int rx_chars; /* Count of characters in queue */
/*****************************************************************************
* com_install() *
*****************************************************************************
* DESCRIPTION: Installs the communications drivers. *
* *
* SYNOPSIS: status = com_install(int portnum); *
* int portnum; Desired port number *
* int status; 0 = Successful installation *
* 1 = Invalid port number *
* 2 = No UART for specified port *
* 3 = Drivers already installed *
* *
* REVISIONS: 18 OCT 89 - RAC - Translated from IBMCOM.PAS *
*****************************************************************************/
const int uart_base[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
const char intnums[] = { 0x0C, 0x0B, 0x0C, 0x0B };
const char i8259levels[] = { 4, 3, 4, 3 };
int com_install(int portnum) {
if (com_installed) /* Drivers already installed */
return 3;
if ((portnum < 1) || (portnum > MAX_PORT)) /* Port number out of bounds */
return 1;
uart_data = uart_base[portnum-1]; /* Set UART I/O addresses */
uart_ier = uart_data + IER; /* for the selected comm */
uart_iir = uart_data + IIR; /* port */
uart_lcr = uart_data + LCR;
uart_mcr = uart_data + MCR;
uart_lsr = uart_data + LSR;
uart_msr = uart_data + MSR;
intnum = intnums[portnum-1]; /* Ditto for interrupt */
i8259bit = 1 << i8259levels[portnum-1]; /* vector and 8259 bit mask */
old_ier = inportb(uart_ier); /* Return an error if we */
outportb(uart_ier, 0); /* can't access the UART */
if (inportb(uart_ier) != 0)
return 2;
disable(); /* Save the original 8259 */
old_i8259_mask = inportb(0x21); /* mask, then disable the */
outportb(0x21, old_i8259_mask | i8259bit); /* 8259 for this interrupt */
enable();
com_flush_